<?php
namespace addons\weixin\library;

use addons\weixin\library\MessageRepositories;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Messages\Article;
use EasyWeChat\Kernel\Messages\Image;
use EasyWeChat\Kernel\Messages\Material;
use EasyWeChat\Kernel\Messages\News;
use EasyWeChat\Kernel\Messages\NewsItem;
use EasyWeChat\Kernel\Messages\Text;
use EasyWeChat\Kernel\Messages\Video;
use EasyWeChat\Kernel\Messages\Voice;
use EasyWeChat\Kernel\Messages\Media;
use app\admin\model\weixin\Reply as WechatReply;
use think\Response;

class WechatService
{
    private static $instance = null;

    public static function options()
    {
        $wechat_data = \app\admin\model\weixin\Config::where(['group' => 'weixin'])->select();
        foreach ($wechat_data as $k => $v) {
            $value = $v->toArray();
            if (in_array($value['type'], ['selects', 'checkbox', 'images', 'files'])) {
                $value['value'] = explode(',', $value['value']);
            }
            if ($value['type'] == 'array') {
                $value['value'] = (array)json_decode($value['value'], true);
            }
            $wechat[$value['name']] = $value['value'];
        }

        $config = [
            'app_id' => isset($wechat['appid']) ? trim($wechat['appid']) : '',
            'secret' => isset($wechat['appsecret']) ? trim($wechat['appsecret']) : '',
            'token'  => isset($wechat['token']) ? trim($wechat['token']) : '',
            'guzzle' => [
                'timeout' => 10.0, // 超时时间（秒）
                'verify'  => false
            ],
        ];
        if (isset($wechat['encode']) && (int)$wechat['encode']>0 && isset($wechat['encodingaeskey']) &&
            !empty($wechat['encodingaeskey'])) {
            $config['aes_key'] = $wechat['encodingaeskey'];
        }
        return $config;
    }

    public static function application($cache = false)
    {
        (self::$instance === null || $cache === true) && (self::$instance = Factory::officialAccount(self::options()));
        return self::$instance;
    }

    public static function serve():Response
    {
        $wechat = self::application(true);
        $server = $wechat->server;
        self::hook($server);
        $response = $server->serve();
        return response($response->getContent());
    }

    /**
     * 监听行为
     * @param Guard $server
     */
    private static function hook($server)
    {
        $server->push(function ($message) {
            //微信消息前置操作
            switch ($message['MsgType']) {
                case 'event':
                    switch (strtolower($message['Event'])) {
                        case 'subscribe':
                            $response = WechatReply::reply('subscribe');//关注回复
                            break;
                        case 'unsubscribe':
                            //用户取消关注公众号前置操作
                            break;
                        case 'scan':
                            $response = WechatReply::reply('subscribe');//扫码关注
                            break;
                        case 'location':
                            $response = MessageRepositories::wechatEventLocation($message);
                            break;
                        case 'click':
                            $response = WechatReply::reply($message['EventKey']);//点击事件
                            break;
                        case 'view':
                            $response = MessageRepositories::wechatEventView($message);
                            break;
                    }
                    break;
                case 'text':
                    $response = WechatReply::reply($message['Content']);
                    break;
                case 'image':
                    $response = MessageRepositories::wechatMessageImage($message);
                    break;
                case 'voice':
                    $response = MessageRepositories::wechatMessageVoice($message);
                    break;
                case 'video':
                    $response = MessageRepositories::wechatMessageVideo($message);
                    break;
                case 'location':
                    $response = MessageRepositories::wechatMessageLocation($message);
                    break;
                case 'link':
                    $response = MessageRepositories::wechatMessageLink($message);
                    break;
                // ... 其它消息
                default:
                    $response = MessageRepositories::wechatMessageOther($message);
                    break;
            }

            return $response ?? false;
        });
    }

    /**
     * 上传永久素材接口
     * @return object
     */
    public static function materialService()
    {
        return self::application()->material;
    }

    /**
     * 客服消息接口
     * @return object
     */
    public static function staffService()
    {
        return self::application()->customer_service;
    }

    /**
     * 微信公众号菜单接口
     * @return object
     */
    public static function menuService()
    {
        return self::application()->menu;
    }

    /**
     * 用户标签接口
     * @return object
     */
    public static function userTagService()
    {
        return self::application()->user_tag;
    }

    /**
     * 回复文本消息
     * @param string $content 文本内容
     * @return Text
     */
    public static function textMessage($content)
    {
        return new Text($content);
    }

    /**
     * 回复图片消息
     * @param string $media_id 媒体资源 ID
     * @return Image
     */
    public static function imageMessage($media_id)
    {
        return new Image($media_id);
    }

    /**
     * 回复视频消息
     * @param string $media_id 媒体资源 ID
     * @param string $title 标题
     * @param string $description 描述
     * @param null $thumb_media_id 封面资源 ID
     * @return Video
     */
    public static function videoMessage($media_id, $title = '', $description = '...', $thumb_media_id = null)
    {
        return new Video(
            $media_id,
            ['title' => $title, 'description' => $description, 'thumb_media_id' => $thumb_media_id]
        );
    }

    /**
     * 回复声音消息
     * @param string $media_id 媒体资源 ID
     * @return Voice
     */
    public static function voiceMessage($media_id)
    {
        return new Voice($media_id);
    }

    /**
     * 回复图文消息
     * @param string|array $title 标题
     * @param string $description 描述
     * @param string $url URL
     * @param string $image 图片链接
     * @return Video
     */
    public static function newsMessage($data)
    {
        $items = [
            new NewsItem([
                'title'       => $data['title'],
                'description' => $data['description'],
                'url'         => $data['url'],
                'image'       => $data['image'],
            ]),
        ];
        return new News($items);
    }

    /**
     * 回复素材消息
     * @param string $type [mpnews、 mpvideo、voice、image]
     * @param string $media_id 素材 ID
     * @return Material
     */
    public static function materialMessage($type, $media_id)
    {
        return new Media($media_id, $type);
    }

    /**
     * 作为客服消息发送
     * @param $to
     * @param $message
     * @return bool
     */
    public static function staffTo($to, $message)
    {
        $staff = self::staffService();
        $staff = is_callable($message) ? $staff->message($message()) : $staff->message($message);
        $res = $staff->to($to)->send();
        return $res;
    }

    /**
     * jsSdk
     * @return object
     */
    public static function jsService()
    {
        return self::application()->jssdk;
    }

    public static function jsSdk($url = '')
    {
        $apiList = [
            'editAddress', 'openAddress', 'updateTimelineShareData', 'updateAppMessageShareData', 'onMenuShareTimeline',
            'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord',
            'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice',
            'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice',
            'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems',
            'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode',
            'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard'
        ];
        $jsService = self::jsService();
        if ($url) {
            $jsService->setUrl($url);
        }
        try {
            return $jsService->buildConfig($apiList, $debug = false, $beta = false, $json = false);
        } catch (\Exception $e) {
            return '{}';
        }
    }

    /**
     * 用户授权
     * @return object
     */
    public static function oauthService()
    {
        return self::application()->oauth;
    }

    /**
     * 用户接口
     * @return object
     */
    public static function userService()
    {
        return self::application()->user;
    }

    /**
     * 获得用户信息
     * @param array|string $openid
     * @return object
     */
    public static function getUserInfo($openid)
    {
        $userService = self::userService();
        $userInfo = $userService->get($openid);
        return $userInfo;
    }

    /**
     * 获得用户列表
     * @param array|string $openid
     * @return object
     */
    public static function getUserList()
    {
        $userService = self::userService();
        $userList = $userService->list();
        return $userList;
    }

    /**
     * 模板消息接口
     * @return \EasyWeChat\Notice\Notice
     */
    public static function noticeService()
    {
        return self::application()->template_message;
    }

    public static function sendTemplate($openid, $templateId, array $data, $url = null, $defaultColor = null)
    {
        $data = [
            'touser' => $openid,
            'template_id' => $templateId,
            'url' => $url,
            'data' => $data
        ];
        return self::noticeService()->send($data);
    }

    /**
     * 微信二维码生成接口
     * @return \EasyWeChat\QRCode\QRCode
     */
    public static function qrcodeService()
    {
        return self::application()->qrcode;
    }

    /**
     * 短链接生成接口
     * @return \EasyWeChat\Url\Url
     */
    public static function urlService()
    {
        return self::application()->url;
    }
}
